package cn.mw.cmdb.param;

import cn.mw.cmdb.entity.InstanceInfo;
import cn.mw.cmdb.entity.InstanceInfoExtend;
import cn.mw.cmdb.entity.ModelInfo;
import cn.mw.cmdb.service.ServiceChoose;
import cn.mw.cmdb.service.impl.CmdbServiceManage;
import cn.mw.cmdb.service.impl.CustomModelServiceImpl;
import cn.mw.cmdb.service.impl.InstanceServiceImpl;
import cn.mw.cmdb.util.CMDBTool;
import cn.mw.components.mongodb.entity.CriteriaOpsType;
import cn.mw.components.mongodb.entity.SearchParam;
import cn.mw.components.mongodb.entity.SubCondition;
import cn.mw.microMonitorCommon.api.user.MwUserApi;
import cn.mw.microMonitorCommon.util.SpringUtils;
import lombok.Data;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.mw.cmdb.entity.InstanceInfo.SearchPrefix;
import static cn.mw.cmdb.entity.PropertyType.relationPath;
import static cn.mw.cmdb.enums.ZabbixAssetsStatusEnum.*;
import static cn.mw.cmdb.processor.TableProcessorCommonInstance.offlineKey;
import static cn.mw.cmdb.util.CMDBTool.genInstanceField;

@Data
public class InstanceSearchParam extends SearchParam implements ServiceChoose, SearchParamConvert {
    private String modelId;

    private String modelName;

    private String instanceId;

    private String groupOrModelId;

    private String bussiness;

    private String brand;

    private String userGroup;

    private String orgs;
    private String orgIds;

    private List<String> instanceIds;

    private List<String> modelIds;
    private List<String> groupIds;
    private List<String> ips;

    //是否查询监控状态
    private boolean enableMonitorStatus;

    //是否忽略权限控制(true表示忽略)
    private boolean ignoreDataAuth;
    //是否全选
    private boolean allFlag;

    private Map<String, Object> data;

    private MwUserApi userApi;

    private String modelViewType;

    private String itemAssetsStatus;

    @Override
    public String getServiceId() {
        return InstanceServiceImpl.ID;
    }

    @Override
    public void convert() throws Exception {


        //资产实例Id查询参数
        String instanceId = getInstanceId();
        if (StringUtils.hasText(instanceId)) {
            this.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getId)
                    , new SubCondition(CriteriaOpsType.is.name(), instanceId));
        }

        List<String> ids = getInstanceIds();
        //如果ids有值，优先以实例ids查询，modelId不设置
        if (CollectionUtils.isNotEmpty(ids)) {
            setModelId(null);
            setModelIds(null);
            this.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getId)
                    , new SubCondition(CriteriaOpsType.in.name(), ids));
        }
        //资产实例Id查询参数
        String modelIdStr = getModelId();
        if (StringUtils.hasText(modelIdStr)) {
            this.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getModelId)
                    , new SubCondition(CriteriaOpsType.is.name(), modelIdStr));
        }

        List<String> modelIds = getModelIds();
        if (CollectionUtils.isNotEmpty(modelIds)) {
            this.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getModelId)
                    , new SubCondition(CriteriaOpsType.in.name(), modelIds));
        }

        List<String> groupIdsKey = getGroupIds();
        if (CollectionUtils.isNotEmpty(groupIdsKey)) {
            this.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getGroupId)
                    , new SubCondition(CriteriaOpsType.in.name(), groupIdsKey));
        }

        List<String> ipsKey = getIps();
        if (CollectionUtils.isNotEmpty(ipsKey)) {
            this.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getInBandIp)
                    , new SubCondition(CriteriaOpsType.in.name(), ipsKey));
        }

        //资产类型树结构查询参数
        String groupOrModelId = getGroupOrModelId();
        if (StringUtils.hasText(groupOrModelId)) {
            this.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getPath)
                    , new SubCondition(CriteriaOpsType.in.name(), groupOrModelId));
        }
        //业务系统树结构查询参数
        String business = getBussiness();
        if (StringUtils.hasText(business)) {
            this.addSubCondition(relationPath
                    , new SubCondition(CriteriaOpsType.like.name(), business));
        }
        //厂商树结构查询参数
        String brand = getBrand();
        if (StringUtils.hasText(brand)) {
            this.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getBrandId)
                    , new SubCondition(CriteriaOpsType.exist.name(), true));
            this.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getBrandId)
                    , new SubCondition(CriteriaOpsType.ne.name(), null));
            this.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getBrandId)
                    , new SubCondition(CriteriaOpsType.is.name(), brand));
        }
        //机构树结构查询参数
        String orgs = getOrgs();
        if (StringUtils.hasText(orgs)) {
            this.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getOrgs)
                    , new SubCondition(CriteriaOpsType.elemMatchMore.name(), orgs));
        }
        //机构树结构查询参数
        String orgIdStr = getOrgIds();
        if (StringUtils.hasText(orgIdStr)) {
            this.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getOrgIds)
                    , new SubCondition(CriteriaOpsType.elemMatch.name(), orgIdStr));
        }

        //用户组树结构查询参数
        String userGroup = getUserGroup();
        if (StringUtils.hasText(userGroup)) {
            this.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getGroups)
                    , new SubCondition(CriteriaOpsType.elemMatch.name(), userGroup));
        }

        //用户组树结构查询参数
        String modelViewType = getModelViewType();
        if (StringUtils.hasText(modelViewType)) {
            //如果是四川银行，模型分组，模型查询时，不做权限过滤
            CmdbServiceManage cmdbServiceManage = SpringUtils.getBean(CmdbServiceManage.class);
            CustomModelServiceImpl modelService = (CustomModelServiceImpl) cmdbServiceManage.getModelService(CustomModelServiceImpl.ID);
            ModelSearchParam searchParam = new ModelSearchParam();
            searchParam.setModelViewType(modelViewType);
            List<ModelInfo> modelInfos = modelService.doSelectList(searchParam);
            List<String> modelViewModelIds = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(modelInfos)) {
                modelViewModelIds = modelInfos.stream().map(s -> s.getId()).collect(Collectors.toList());
            }
            this.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getModelId)
                    , new SubCondition(CriteriaOpsType.in.name(), modelViewModelIds));
        }

        //资产状态查询参数
        String itemAssetsStatusKey = getItemAssetsStatus();
        if (StringUtils.hasText(itemAssetsStatusKey)) {
            //资产状态异常
            if (ABNORMAL.getName().equals(itemAssetsStatusKey)) {
                //获取警告和异常的数据
                this.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getItemAssetsStatus)
                        , new SubCondition(CriteriaOpsType.in.name(), Arrays.asList(ALERT.getName(), ABNORMAL.getName())));
            } else if (NORMAL.getName().equals(itemAssetsStatusKey)) {
                //获取正常和未监控的数据
                this.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getItemAssetsStatus)
                        , new SubCondition(CriteriaOpsType.in.name(), Arrays.asList(UNKNOWN.getName(), NORMAL.getName())));
            } else if (offlineKey.equals(itemAssetsStatusKey)) {
                //获取正常和未监控的数据
                this.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getItemAssetsStatus)
                        , new SubCondition(CriteriaOpsType.in.name(), Arrays.asList(SHUTDOWN.getName())));
            } else {
                this.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getItemAssetsStatus)
                        , new SubCondition(CriteriaOpsType.is.name(), itemAssetsStatusKey));
            }
        }

        if (getSortName() != null) {
            List<String> list = genInstanceField(InstanceInfoExtend.class);
            if (list != null && !list.contains(getSortName())) {
                setSortName(SearchPrefix + "." + getSortName());
            }
        }

        if (getData() != null) {
            //获取实例实体类字段
            for (Map.Entry<String, Object> entry : getData().entrySet()) {
                if (entry.getValue() instanceof List<?>) {
                    this.addSubCondition(entry.getKey()
                            , new SubCondition(CriteriaOpsType.in.name(), entry.getValue()));
                } else {
                    this.addSubCondition(entry.getKey()
                            , new SubCondition(CriteriaOpsType.is.name(), entry.getValue()));
                }
            }
        }
    }
}
